package com.fy.fyspace.controller;

import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
//import com.fy.fyspace.common.annotation.SaSpaceCheckPermission;
import com.fy.fyspace.common.auth.StpKit;
import com.fy.fyspace.common.auth.annotation.SpaceAuth;
import com.fy.fyspace.common.auth.authenum.SpaceUserPermissionEnum;
import com.fy.fyspace.common.auth.authenum.SpaceUserRoleEnum;
import com.fy.fyspace.common.auth.model.SpaceUser;
import com.fy.fyspace.common.auth.model.SpaceUserPermission;
import com.fy.fyspace.common.auth.model.SpaceUserRole;
import com.fy.fyspace.constant.KeysConstant;
import com.fy.fyspace.mapper.SpaceUserMapper;
import com.fy.fyspace.mapper.SpaceUserPermissionMapper;
import com.fy.fyspace.mapper.SpaceUserRoleMapper;
import com.fy.fyspace.model.enums.spaceuser.SpaceUserStatusEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.Set;

@RestController
@Slf4j
@RequestMapping("sa-token")
public class SaTokenController {

    @Autowired
    private SpaceUserMapper spaceUserMapper;

    @Autowired
    private SpaceUserRoleMapper spaceUserRoleMapper;

    @Autowired
    private SpaceUserPermissionMapper spaceUserPermissionMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    // 测试登录 ---- http://localhost:8888/acc/doLogin?name=zhang&pwd=123456
    @PostMapping("doLogin")
    public SaResult doLogin() {
        try {
            // TODO: 实际项目中需要进行用户名密码验证
            Long userId = 1L; // 这里应该是验证成功后获取到的用户ID

            // 查询空间用户信息
            LambdaQueryWrapper<SpaceUser> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(SpaceUser::getUserId, userId)
                    .eq(SpaceUser::getIsDelete, SpaceUserStatusEnum.NOT_DELETE.getStatus());
            SpaceUser spaceUser = spaceUserMapper.selectOne(wrapper);

            if (spaceUser == null) {
                return SaResult.error("用户不存在或已被禁用");
            }

            // 清除旧的登录信息（如果有）
            if (StpKit.SPACE.isLogin()) {
                clearUserAuthInfo(userId);
                StpKit.SPACE.logout();
            }

            // 查询用户角色
            Long userRoleId = spaceUser.getUserRoleId();
            if (userRoleId == null) {
                return SaResult.error("用户角色未配置");
            }

            LambdaQueryWrapper<SpaceUserRole> wp = new LambdaQueryWrapper<>();
            wp.eq(SpaceUserRole::getId, userRoleId)
                    .eq(SpaceUserRole::getIsDelete, SpaceUserStatusEnum.NOT_DELETE.getStatus());
            List<SpaceUserRole> spaceUserRoles = spaceUserRoleMapper.selectList(wp);

            if (spaceUserRoles.isEmpty()) {
                return SaResult.error("用户角色不存在或已被禁用");
            }

            SpaceUserRole userRole = spaceUserRoles.get(0);

            // 登录用户（只使用SPACE登录系统）
            StpKit.SPACE.login(userId);

            // 存储角色和权限信息到Redis
            String roleKey = KeysConstant.SPACE_ROLE_REDIS_KEY + userId;
            String permKey = KeysConstant.SPACE_PERMISSION_REDIS_KEY + userId;

            // 存储角色优先级
            redisTemplate.opsForSet().add(roleKey, userRole.getId());

            // 存储权限
            List<Long> permissionIds = userRole.getSpaceUserPermissionIds();
            if (permissionIds != null && !permissionIds.isEmpty()) {
                List<SpaceUserPermission> permissions = spaceUserPermissionMapper.selectBatchIds(permissionIds);
                for (SpaceUserPermission permission : permissions) {
                    redisTemplate.opsForSet().add(permKey, permission.getId());
                }
            }

            log.info("用户{}登录成功，角色和权限信息已存入Redis", userId);
            return SaResult.ok("登录成功").setData(StpKit.SPACE.getTokenValue());

        } catch (Exception e) {
            log.error("登录过程发生错误", e);
            return SaResult.error("登录失败：" + e.getMessage());
        }
    }

    /**
     * 清除用户的权限和角色缓存
     */
    private void clearUserAuthInfo(Long userId) {
        try {
            // 清除角色缓存
            Set<String> roleKeys = redisTemplate.keys(KeysConstant.SPACE_ROLE_REDIS_KEY + userId);
            if (roleKeys != null) {
                for (String roleKey : roleKeys) {
                    redisTemplate.opsForSet().remove(roleKey, userId);
                }
            }

            // 清除权限缓存
            Set<String> permKeys = redisTemplate.keys(KeysConstant.SPACE_PERMISSION_REDIS_KEY + userId);
            if (permKeys != null) {
                for (String permKey : permKeys) {
                    redisTemplate.opsForSet().remove(permKey, userId);
                }
            }
        } catch (Exception e) {
            log.error("清除用户{}的权限缓存时发生错误", userId, e);
        }
    }

    // 查询登录状态 ---- http://localhost:8888/acc/isLogin
    @GetMapping("isLogin")
    public SaResult isLogin() {
        log.info("登录id:{}", StpKit.SPACE.getLoginId());
        return SaResult.ok("是否登录：" + StpKit.SPACE.isLogin());
    }

    // 查询 Token 信息 ---- http://localhost:8888/acc/tokenInfo
    @GetMapping("tokenInfo")
    public SaResult tokenInfo() {
        return SaResult.data(StpUtil.getTokenInfo());
    }

    // 测试注销 ---- http://localhost:8888/acc/logout
    @PostMapping("logout")
    public SaResult logout() {
        StpUtil.logout();
        return SaResult.ok();
    }

    @GetMapping("/checkLogin")
    public SaResult checkLogin() {
        StpUtil.checkLogin();
        return SaResult.ok("登录状态:");
    }

    @GetMapping("getAll")
    @SpaceAuth(role = SpaceUserRoleEnum.SPACE_ADMIN)
    public SaResult getAll() {
        return SaResult.ok("ok");
    }

    /**
     * 需要空间管理员角色才能访问
     */
    @GetMapping("admin")
    @SpaceAuth(role = SpaceUserRoleEnum.SPACE_ADMIN)
    public SaResult adminOnly() {
        return SaResult.ok("您是管理员，可以访问此接口");
    }

    /**
     * 需要图片上传权限才能访问
     */
    @PostMapping("upload")
    @SpaceAuth(permissions = { SpaceUserPermissionEnum.PICTURE_UPLOAD })
    public SaResult uploadPicture() {
        return SaResult.ok("您有上传权限，可以上传图片");
    }

    /**
     * 需要同时具备多个权限
     */
    @PostMapping("manage-pictures")
    @SpaceAuth(permissions = {
            SpaceUserPermissionEnum.PICTURE_UPLOAD,
            SpaceUserPermissionEnum.PICTURE_DELETE,
            SpaceUserPermissionEnum.PICTURE_EDIT
    })
    public SaResult managePictures() {
        return SaResult.ok("您具备所有需要的图片管理权限");
    }

    /**
     * 需要多个权限中的任意一个
     */
    @PostMapping("picture-operation")
    @SpaceAuth(permissions = {
            SpaceUserPermissionEnum.PICTURE_UPLOAD,
            SpaceUserPermissionEnum.PICTURE_EDIT
    })
    public SaResult pictureOperation() {
        return SaResult.ok("您具备上传或编辑权限之一");
    }

    /**
     * 普通成员就可以访问的接口
     */
    @GetMapping("member-access")
    @SpaceAuth(role = SpaceUserRoleEnum.SPACE_MEMBER)
    public SaResult memberAccess() {
        return SaResult.ok("您是空间成员，可以访问此接口");
    }

    /**
     * 访客也可以访问的接口（默认权限）
     */
    @GetMapping("visitor-access")
    @SpaceAuth
    public SaResult visitorAccess() {
        return SaResult.ok("这是一个所有人都能访问的接口");
    }
}
